<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { merge } from 'lodash-es'
import { useRoute } from 'vue-router'
import { sensitiveConfig } from '../../config'
import type { ICaseTableItem } from '../../type'
import { runCase, updateCase } from '@/api/cases'
import { scatterBaseOptions } from '@/components/ui/chart/src/scatterOptions'
import useStore from '@/stores'
import { useFetch } from '@/composables/useFetch'
import { isEmptyObject } from '@/utils'
import { useCaseResult } from '@/views/cases/components/useCaseResult'

const route = useRoute()
const { cases } = useStore()
const caseInfo = computed(() => cases.caseInfo)
const detailData = computed(() => caseInfo.value?.jsonArgs ? JSON.parse(caseInfo.value?.jsonArgs) : null)
const sensitiveFormRef = ref()
const scatterOptionsList = ref([scatterBaseOptions])

const { loading: runLoading, execute: runCaseExecute } = useFetch((parmas: any = {}) => runCase(parmas))
const { execute: updateCaseExecute } = useFetch((parmas: ICaseTableItem) => updateCase(parmas))

// 获取结果
const { sensitivityResult, sensitiveLoading, onClickRefreshAllAction } = useCaseResult()
watch(() => sensitivityResult.value, () => {
  if (isEmptyObject(sensitivityResult.value)) {
    scatterOptionsList.value = [scatterBaseOptions]
    return
  }

  _setChartOption(sensitivityResult.value)
}, { deep: true })

// 共用一个按钮加载状态
watch(() => runLoading.value, (val: boolean) => {
  cases.setCaseRunLoading(val)
})

// 保存表单信息
watch([() => sensitiveFormRef.value?.model], () => {
  cases.initFormInfoSkip()
  const formInfo = Object.assign({}, cases.formInfo, { Sensitivity_analysis: { ...sensitiveFormRef.value.model, skip: false } })
  cases.saveFormInfo(formInfo)
}, { deep: true })

// 接口的表单字段有变化需要重新回填表单
// watch(() => detailData.value?.Sensitivity_analysis, (nVal: any) => {
//   if (nVal)
//     initForm()
// }, { deep: true })

onMounted(() => {
  initForm()
  // handleFormInteraction()
})

onBeforeUnmount(() => {
  sensitivityResult.value = null as any
  scatterOptionsList.value = null as any
})

function initForm() {
  if (detailData.value && !isEmptyObject(detailData.value)) {
    const [analysisStep, analysisStepVar] = handleDRAndClusterDefault(detailData.value)
    sensitiveFormRef.value.model = { ...detailData.value.Sensitivity_analysis, analysis_step: analysisStep, analysis_var: analysisStepVar }
  }
}

function handleDRAndClusterDefault(detailData: any) {
  const drMethod = detailData.DR.method
  const clusterMethod = detailData.Cluster.method
  const drMap = new Map([
    [0, 'DR:PCA'],
    [1, 'DR:PCA'],
    [2, 'DR:Umap'],
    [3, 'DR:Pacmap'],
    [4, 'DR:ICA'],
    [5, 'DR:SPE'],
    [6, 'DR:t-SNE'],
    [7, 'DR:TriMap'],
  ])
  const clusterMap = new Map([
    [0, 'Cluster:kmeans'],
    [1, 'Cluster:kmeans'],
    [2, 'Cluster:DBSCAN'],
    [3, 'Cluster:meanshift'],
    [4, 'Cluster:birch'],
    [5, 'Cluster:HDBSCAN'],
  ])
  const varMap = new Map([
    ['DR:PCA', ['n_components']],
    ['DR:Umap', ['n_components']],
    ['DR:Pacmap', ['n_components', 'n_heigh', 'MN_ratio', 'FP_ratio', 'num_iters']],
    ['DR:ICA', ['n_components']],
    ['DR:SPE', ['n_components', 'n_neigh']],
    ['DR:t-SNE', ['n_components', 'perplexity']],
    ['DR:TriMap', ['n_components']],
    ['Cluster:kmeans', ['Cluster_numbers']],
    ['Cluster:DBSCAN', ['minsamp1', 'epsilon']],
    ['Cluster:meanshift', ['Cluster_numbers', 'bandwidth1']],
    ['Cluster:birch', ['nclust2', 'threshold1', 'branch_factor']],
    ['Cluster:HDBSCAN', ['minsamp2']],
  ])
  const step = drMap.get(drMethod) || clusterMap.get(clusterMethod) || 'DR:PCA'
  return [step, varMap.get(step)![0] || 'n_components']
}

function handleFiveFormDRAndCluster() {
  const drMethod = detailData.value.DR.method
  const clusterMethod = detailData.value.Cluster.method
  const drMap = new Map([
    [0, 'DR:PCA'],
    [1, 'DR:PCA'],
    [2, 'DR:Umap'],
    [3, 'DR:Pacmap'],
    [4, 'DR:ICA'],
    [5, 'DR:SPE'],
    [6, 'DR:t-SNE'],
    [7, 'DR:TriMap'],
  ])
  const clusterMap = new Map([
    [0, 'Cluster:kmeans'],
    [1, 'Cluster:kmeans'],
    [2, 'Cluster:DBSCAN'],
    [3, 'Cluster:meanshift'],
    [4, 'Cluster:birch'],
    [5, 'Cluster:HDBSCAN'],
  ])
  return [drMap.get(drMethod), clusterMap.get(clusterMethod)]
}

const sensitiveFormOptions = ref(sensitiveConfig.sensitiveFormOptions)
watch(() => sensitiveFormRef.value?.model.analysis_step, () => {
  _handleAnalysiStep()
})

function _handleAnalysiStep() {
  const map = new Map([
    ['DR:PCA', ['n_components']],
    ['DR:Umap', ['n_components']],
    ['DR:Pacmap', ['n_components', 'n_heigh', 'MN_ratio', 'FP_ratio', 'num_iters']],
    ['DR:ICA', ['n_components']],
    ['DR:SPE', ['n_components', 'n_neigh']],
    ['DR:t-SNE', ['n_components', 'perplexity']],
    ['DR:TriMap', ['n_components']],
    ['Cluster:kmeans', ['Cluster_numbers']],
    ['Cluster:DBSCAN', ['minsamp1', 'epsilon']],
    ['Cluster:meanshift', ['Cluster_numbers', 'bandwidth1']],
    ['Cluster:birch', ['nclust2', 'threshold1', 'branch_factor']],
    ['Cluster:HDBSCAN', ['minsamp2']],
  ])
  let analysisStep = sensitiveFormRef.value?.model.analysis_step || 'DR:PCA'
  let analysisStepVar = sensitiveFormRef.value?.model.analysis_var || 'n_components'
  // 后端不好修改，前端打补丁。。。
  // 当初始值是旧版本的Cluster或者DR，并且前面五步没有选择method, 替换成新版本的默认值方便case在初次创建后的默认值回填
  if (detailData.value.DR.method || detailData.value.Cluster.method) {
    const index = detailData.value.DR.method ? 0 : 1
    if (analysisStep === 'Cluster' || analysisStep === 'DR') {
      analysisStep = handleFiveFormDRAndCluster()[index]
      analysisStepVar = map.get(analysisStep)![0]
    }
  }
  else if (analysisStep === 'Cluster' || analysisStep === 'DR') {
    analysisStep = 'DR:PCA'
    analysisStepVar = 'n_components'
  }

  // 拿到新的analysisVarList
  const stepArr = handleFiveFormDRAndCluster()
  const stepChildren = stepArr.map((item: any) => {
    return {
      type: 'select-option',
      label: item,
      value: item,
    }
  })
  sensitiveFormOptions.value = sensitiveConfig.sensitiveFormOptions.map((item: any) => {
    if (item.prop === 'analysis_step') {
      return {
        ...item,
        children: stepChildren,
        value: analysisStep,
      }
    }
    return item
  }) as any

  // 新的表单赋值后analysis_step默认值是空的，需要重新赋值analysis_step
  const analysis_stepVar = sensitiveConfig.sensitiveFormOptions.find((item: any) => item.prop === 'analysis_var')!
  const analysis_start_value = sensitiveConfig.sensitiveFormOptions.find((item: any) => item.prop === 'start_value')!
  const analysis_end_value = sensitiveConfig.sensitiveFormOptions.find((item: any) => item.prop === 'end_value')!
  const analysis_step_value = sensitiveConfig.sensitiveFormOptions.find((item: any) => item.prop === 'step_value')!
  const analysisVarList = map.get(analysisStep) || []
  const stepVarChildren = analysisVarList.map((item: any) => {
    return {
      type: 'select-option',
      label: item,
      value: item,
    }
  })
  analysis_stepVar.children = stepVarChildren as any
  analysis_stepVar.value = analysisVarList.length ? analysisVarList[0] : analysisStepVar
  analysis_start_value.value = detailData.value?.Sensitivity_analysis.start_value
  analysis_end_value.value = detailData.value?.Sensitivity_analysis.end_value
  analysis_step_value.value = detailData.value?.Sensitivity_analysis.step_value

  const formInfo = Object.assign({}, cases.formInfo, { Sensitivity_analysis: {
    analysis_step: analysisStep,
    analysis_var: analysis_stepVar.value,
    start_value: analysis_start_value.value,
    end_value: analysis_end_value.value,
    step_value: analysis_step_value.value,
    skip: false,
  },
  })
  cases.saveFormInfo(formInfo)
}

function onClickSubmitRun() {
  const validate = sensitiveFormRef.value.validate()

  validate().then(async () => {
    // 后端进行缓存全量参数
    await updateCaseExecute({ caseId: route.query.id, jsonArgs: JSON.stringify(cases.formInfo) })

    // 运行操作
    await runCaseExecute({ caseId: route.query.id })
  })
}

function _setChartOption(resultData: any) {
  const { sen_2d } = resultData

  scatterOptionsList.value = sen_2d?.map((item: any) => {
    const options = merge(
      {},
      scatterBaseOptions,
      {
        legend: {
          data: item.serie_names,
        },
        series: item.series,
      },
    )
    return options
  })
}

defineExpose({ onClickSubmitRun, onClickRefreshAllAction })
</script>

<template>
  <div class="case-sensitive-wrapper case-form-wrapper">
    <GpForm ref="sensitiveFormRef" layout="vertical" :options="sensitiveFormOptions" class="gp__grid-three" />
    <div class="chart-box">
      <a-card title="Sensitive 2d">
        <a-spin tip="loading..." :spinning="sensitiveLoading">
          <div class="chart-wrapper">
            <template v-for="(scatterItem, index) in scatterOptionsList" :key="scatterItem.id">
              <GpChart
                :id="`case${index}Scatter`"
                :options="scatterItem"
                class="chart-item"
              />
            </template>
          </div>
        </a-spin>
      </a-card>
    </div>
  </div>
</template>

<style lang="less" scoped>
@import url('../../common.less');
.case-sensitive-wrapper {
  .chart-wrapper {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }
}
</style>
